#include "SocketServer.h"
#include "Exception.h"
#include "NamedIndex.h"
#include "Utils.h"
#include "SharedCriticalSection.h"
#include "ThreadPool.h"
#include <DbgHelp.h>
using JetByteTools::Win32::_tstring;
using JetByteTools::Win32::CException;
using JetByteTools::Win32::Output;
using JetByteTools::Win32::CManualResetEvent;
using JetByteTools::Win32::CNamedIndex;
using JetByteTools::Win32::CInstrumentedSharedCriticalSection;
using JetByteTools::Win32::CSharedCriticalSection;
using JetByteTools::Win32::GetModuleFileName;
using JetByteTools::Win32::CThreadPool;
#include "TangoThreadPool.h"
#include "TangoIOPool.h"
#include "TangoSocketServer.h"
CManualResetEvent shutdownEvent;
CManualResetEvent pauseResumeEvent;

//------------------------------------------//
#ifdef ARCH64
	#define TG_TRANSSERVER_PORT 5023
#else
	#define TG_TRANSSERVER_PORT 5024
#endif
//------------------------------------------//
void CreateDumpFile(LPCSTR lpstrDumpFilePathName, EXCEPTION_POINTERS *pException)
{
	HANDLE hDumpFile = CreateFileA(lpstrDumpFilePathName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	MINIDUMP_EXCEPTION_INFORMATION dumpInfo;
	dumpInfo.ExceptionPointers = pException;
	dumpInfo.ThreadId = GetCurrentThreadId();
	dumpInfo.ClientPointers = TRUE;

	MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), hDumpFile, MiniDumpWithFullMemory, &dumpInfo, NULL, NULL);

	CloseHandle(hDumpFile);
}

LONG ApplicationCrashHandler(EXCEPTION_POINTERS *pException)
{
	char path[MAX_PATH] = { 0 };
	sprintf(path, "c:\\%d.dmp", ::GetTickCount());
	CreateDumpFile(path, pException);
	::ExitThread(0);
	return EXCEPTION_CONTINUE_EXECUTION;
}

int _tmain(int argc, _TCHAR* argv[])
{
	SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)ApplicationCrashHandler);

	WSADATA t_wsa;
	WORD wVers;
	int iError;
	wVers = MAKEWORD(2, 2);
	iError = WSAStartup(wVers, &t_wsa);
	try{
		CNamedIndex userDataSlots;
		CTangoThreadPool businessLogicPool(userDataSlots,
			5,                            // initial number of threads to create
			5,                            // minimum number of threads to keep in the pool
			150,                           // maximum number of threads in the pool
			5,                            // maximum number of "dormant" threads
			5000,                         // pool maintenance period (millis)
			100,                          // dispatch timeout (millis)
			10000,                        // dispatch timeout for when pool is at max threads
			2,                           // number of reads to post
			true,                         // maintain packet order with sequence numbers
			true);
		businessLogicPool.Start();
		const size_t numberOfUserDataSlots = userDataSlots.Lock();
		CTangoIOPool ioPool(0);
		ioPool.Start();
		CSharedCriticalSection lockFactory(47);
		CTangoSocketServer server(lockFactory,
			ioPool,
			INADDR_ANY,                   // address to listen on
			TG_TRANSSERVER_PORT,          // port to listen on
			10,                           // max number of sockets to keep in the pool
			10,                           // max number of buffers to keep in the pool
			64 * 1024,                         // buffer size 
			numberOfUserDataSlots,
			businessLogicPool,
			65536,                        // max message size
			true,                         // maintain read packet order with sequence numbers
			true,                         // maintain write packet order with sequence numbers (required for read packet ordering!)
			true);
		server.Start();
		server.StartAcceptingConnections();
		HANDLE handlesToWaitFor[2];
		handlesToWaitFor[0] = shutdownEvent.GetEvent();
		handlesToWaitFor[1] = pauseResumeEvent.GetEvent();
		bool accepting = true;
		bool done = false;
		while (!done)
		{
			DWORD waitResult = ::WaitForMultipleObjects(2, handlesToWaitFor, false, INFINITE);

			if (waitResult == WAIT_OBJECT_0)
			{
				done = true;
			}
			else if (waitResult == WAIT_OBJECT_0 + 1)
			{
				if (accepting)
				{
					server.StopAcceptingConnections();
					//					server2.StopAcceptingConnections();
				}
				else
				{
					server.StartAcceptingConnections();
					//					server2.StartAcceptingConnections();
				}

				accepting = !accepting;
			}
			else
			{
				done = true;
			}
		}

		//server2.WaitForShutdownToComplete();
		businessLogicPool.WaitForShutdownToComplete(15000, true);

		ioPool.WaitForShutdownToComplete();
		server.WaitForShutdownToComplete();
	}
	catch (const CException &e)
	{

	}
	catch (...)
	{

	}
	WSACleanup();
	return 0;
}

//------------------------------------------//
